#include <linux/module.h>
#include <linux/timer.h>
#include <linux/tty.h>
#include <linux/kd.h>
#include <linux/console_struct.h>

#define BLINK_DELAY HZ/4
#define ALL_LEDS_ON 0x07
#define RESTORE_LEDS_STATUS 0xff

struct timer_list slam_timer;
char led_status = 0;

extern struct vc vc_cons [MAX_NR_CONSOLES];
extern int fg_console;

static struct tty_driver * slam_tty_driver;

void keyboard_led_timer_function(unsigned long data)
{
	int *pre_status = (int *)data;

	if (*pre_status == ALL_LEDS_ON)
	      *pre_status = RESTORE_LEDS_STATUS;
	else
	      *pre_status = ALL_LEDS_ON;
	(slam_tty_driver->ops->ioctl)(vc_cons[fg_console].d->port.tty, KDSETLED, *pre_status);
	mod_timer(&slam_timer, jiffies + msecs_to_jiffies(BLINK_DELAY));
}

static __init int timer_keyboard_led_init(void)
{
	slam_tty_driver = vc_cons[fg_console].d->port.tty->driver;

	setup_timer(&slam_timer, keyboard_led_timer_function, (unsigned long)&led_status);
	mod_timer(&slam_timer, jiffies + msecs_to_jiffies(BLINK_DELAY));

	return 0;
}

static __exit void timer_keyboard_led_exit(void)
{
	del_timer(&slam_timer);
	(slam_tty_driver->ops->ioctl)(vc_cons[fg_console].d->port.tty, KDSETLED, RESTORE_LEDS_STATUS);
}

module_init(timer_keyboard_led_init);
module_exit(timer_keyboard_led_exit);
